package simpledb;

import simpledb.common.DbException;
import simpledb.common.Type;
import simpledb.common.Utility;
import simpledb.storage.*;
import simpledb.transaction.TransactionAbortedException;
import simpledb.transaction.TransactionId;

import java.io.File;
import java.io.IOException;

/**
 * SimpleDB 的主类，提供命令行接口用于：
 * - 将文本文件转换为数据库可用的二进制数据文件（.dat）
 * - 打印数据库文件中的元组内容
 * - 调用解析器处理 SQL 查询语句（如果存在）
 */
public class SimpleDb {

    public static void main(String[] args) throws DbException, TransactionAbortedException {
        // 根据命令行参数执行不同操作
        switch (args[0]) {
            case "convert":
                try {
                    if (args.length < 3 || args.length > 5) {
                        System.err.println("转换命令需要3到5个参数");
                        return;
                    }

                    // 获取输入文件和目标文件
                    File sourceTxtFile = new File(args[1]);
                    File targetDatFile = new File(args[1].replaceAll(".txt", ".dat"));

                    // 获取字段数量
                    int numOfAttributes = Integer.parseInt(args[2]);

                    // 初始化字段类型数组
                    Type[] ts = new Type[numOfAttributes];
                    char fieldSeparator = ','; // 默认字段分隔符为逗号

                    // 如果没有指定字段类型，则默认全部是 INT 类型
                    if (args.length == 3) {
                        for (int i = 0; i < numOfAttributes; i++)
                            ts[i] = Type.INT_TYPE;
                    } else {
                        String typeString = args[3];
                        String[] typeStringAr = typeString.split(",");
                        if (typeStringAr.length != numOfAttributes) {
                            System.err.println("字段类型数量与列数不一致");
                            return;
                        }
                        int index = 0;
                        for (String s : typeStringAr) {
                            if (s.equalsIgnoreCase("int"))
                                ts[index++] = Type.INT_TYPE;
                            else if (s.equalsIgnoreCase("string"))
                                ts[index++] = Type.STRING_TYPE;
                            else {
                                System.err.println("未知类型: " + s);
                                return;
                            }
                        }

                        // 如果有指定字段分隔符，则使用该分隔符
                        if (args.length == 5)
                            fieldSeparator = args[4].charAt(0);
                    }

                    // 使用 HeapFileEncoder 工具将文本文件转换为数据库格式的 .dat 文件
                    HeapFileEncoder.convert(sourceTxtFile, targetDatFile, BufferPool.getPageSize(), numOfAttributes,
                        ts, fieldSeparator);

                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                break;

            case "print":
                // 打印一个数据库文件的内容（.dat 文件）
                File tableFile = new File(args[1]);
                int columns = Integer.parseInt(args[2]);
                DbFile table = Utility.openHeapFile(columns, tableFile); // 打开堆文件
                TransactionId tid = new TransactionId(); // 创建事务 ID
                DbFileIterator it = table.iterator(tid); // 获取迭代器

                if (null == it) {
                    System.out.println("错误：HeapFile.iterator(TransactionId tid) 尚未实现！");
                } else {
                    it.open();
                    while (it.hasNext()) {
                        Tuple t = it.next();
                        System.out.println(t); // 输出每个元组
                    }
                    it.close();
                }
                break;

            case "parser":
                // 调用解析器模块来处理 SQL 查询语句
                String[] newargs = new String[args.length - 1];
                System.arraycopy(args, 1, newargs, 0, args.length - 1);

                try {
                    // 动态加载 Parser 类 —— 如果不存在，输出提示信息
                    Class<?> c = Class.forName("simpledb.Parser");
                    Class<?> s = String[].class;

                    java.lang.reflect.Method m = c.getMethod("main", s);
                    m.invoke(null, (Object) newargs);
                } catch (ClassNotFoundException cne) {
                    System.out.println("找不到 Parser 类 —— 可能你正在运行 lab1？");
                } catch (Exception e) {
                    System.out.println("解析器调用出错。");
                    e.printStackTrace();
                }
                break;

            default:
                System.err.println("未知命令: " + args[0]);
                System.exit(1);
        }
    }
}
